using Microsoft.Extensions.Logging;
using System;
using System.Net;
using System.Net.Http;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;

namespace DocumentCreationSystem.Services
{
    /// <summary>
    /// 网络恢复服务
    /// 提供网络连接检测和恢复功能
    /// </summary>
    public class NetworkRecoveryService
    {
        private readonly ILogger<NetworkRecoveryService> _logger;
        private readonly string[] _testUrls = {
            "https://www.baidu.com",
            "https://www.google.com",
            "https://open.bigmodel.cn",
            "https://api.deepseek.com"
        };

        public NetworkRecoveryService(ILogger<NetworkRecoveryService> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// 检查网络连接状态
        /// </summary>
        public async Task<bool> IsNetworkAvailableAsync()
        {
            try
            {
                // 首先检查本地网络接口
                if (!NetworkInterface.GetIsNetworkAvailable())
                {
                    return false;
                }

                // 尝试ping测试
                using var ping = new Ping();
                var reply = await ping.SendPingAsync("8.8.8.8", 5000);
                if (reply.Status == IPStatus.Success)
                {
                    return true;
                }

                // 如果ping失败，尝试HTTP请求
                using var httpClient = new HttpClient();
                httpClient.Timeout = TimeSpan.FromSeconds(10);

                foreach (var url in _testUrls)
                {
                    try
                    {
                        var response = await httpClient.GetAsync(url);
                        if (response.IsSuccessStatusCode)
                        {
                            return true;
                        }
                    }
                    catch
                    {
                        // 继续尝试下一个URL
                    }
                }

                return false;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "网络连接检查失败");
                return false;
            }
        }

        /// <summary>
        /// 等待网络恢复
        /// </summary>
        public async Task<bool> WaitForNetworkRecoveryAsync(TimeSpan timeout, CancellationToken cancellationToken = default)
        {
            var startTime = DateTime.Now;
            var checkInterval = TimeSpan.FromSeconds(5);

            _logger.LogInformation("开始等待网络恢复...");

            while (DateTime.Now - startTime < timeout && !cancellationToken.IsCancellationRequested)
            {
                if (await IsNetworkAvailableAsync())
                {
                    _logger.LogInformation("网络连接已恢复");
                    return true;
                }

                _logger.LogDebug($"网络未恢复，{checkInterval.TotalSeconds}秒后重试...");
                await Task.Delay(checkInterval, cancellationToken);
            }

            if (cancellationToken.IsCancellationRequested)
            {
                _logger.LogInformation("网络恢复等待被取消");
            }
            else
            {
                _logger.LogWarning($"网络恢复等待超时（{timeout.TotalMinutes}分钟）");
            }

            return false;
        }

        /// <summary>
        /// 智能重试执行
        /// </summary>
        public async Task<T> ExecuteWithNetworkRetryAsync<T>(
            Func<Task<T>> operation,
            int maxRetries = 5,
            TimeSpan? networkRecoveryTimeout = null,
            CancellationToken cancellationToken = default)
        {
            var recoveryTimeout = networkRecoveryTimeout ?? TimeSpan.FromMinutes(10);
            var baseDelay = TimeSpan.FromSeconds(2);

            for (int attempt = 1; attempt <= maxRetries; attempt++)
            {
                try
                {
                    return await operation();
                }
                catch (Exception ex) when (IsNetworkException(ex) && attempt < maxRetries)
                {
                    _logger.LogWarning($"网络异常，尝试 {attempt}/{maxRetries}: {ex.Message}");

                    // 检查网络状态
                    if (!await IsNetworkAvailableAsync())
                    {
                        _logger.LogInformation("检测到网络中断，等待网络恢复...");
                        
                        var recovered = await WaitForNetworkRecoveryAsync(recoveryTimeout, cancellationToken);
                        if (!recovered)
                        {
                            throw new InvalidOperationException("网络恢复超时，无法继续执行", ex);
                        }
                    }

                    // 指数退避延迟
                    var delay = TimeSpan.FromMilliseconds(baseDelay.TotalMilliseconds * Math.Pow(2, attempt - 1));
                    await Task.Delay(delay, cancellationToken);
                }
                catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
                {
                    _logger.LogInformation("操作被取消");
                    throw;
                }
            }

            throw new InvalidOperationException($"操作失败，已重试 {maxRetries} 次");
        }

        /// <summary>
        /// 判断是否为网络相关异常
        /// </summary>
        private bool IsNetworkException(Exception ex)
        {
            return ex is HttpRequestException ||
                   ex is TaskCanceledException ||
                   ex is SocketException ||
                   ex is System.IO.IOException ||
                   (ex.InnerException != null && IsNetworkException(ex.InnerException)) ||
                   ex.Message.Contains("SSL connection") ||
                   ex.Message.Contains("远程主机强迫关闭") ||
                   ex.Message.Contains("connection") ||
                   ex.Message.Contains("network") ||
                   ex.Message.Contains("timeout");
        }

        /// <summary>
        /// 获取网络状态描述
        /// </summary>
        public async Task<string> GetNetworkStatusAsync()
        {
            try
            {
                var isAvailable = await IsNetworkAvailableAsync();
                if (isAvailable)
                {
                    return "网络连接正常";
                }

                // 详细检查网络状态
                if (!NetworkInterface.GetIsNetworkAvailable())
                {
                    return "本地网络接口不可用";
                }

                return "网络连接异常，可能是DNS或防火墙问题";
            }
            catch (Exception ex)
            {
                return $"网络状态检查失败: {ex.Message}";
            }
        }
    }
}
